; ==================================================================
; MikeOS -- The Mike Operating System kernel
; Copyright (C) 2006 - 2013 MikeOS Developers -- see doc/LICENSE.TXT
;
; COMMAND LINE INTERFACE
; ==================================================================
; pos32 - The Portable OS Kernel
; Copyright (C) 2012-2013 POS Developers -- see ./POSLIC.txt

os_command_line:
	call os_clear_screen
	mov bl, [color]	; White on red
	mov dl, 0		; Start X position
	mov dh, 1		; Start Y position
	mov si, 80	; Width
	mov di, 50	; Finish Y position
	call os_draw_block
	call draw_bck
get_cmd:		
	; Main processing loop
	mov di, input			; Clear input buffer each time
	mov al, 0
	mov cx, 256
	rep stosb
	
	mov di, command			; And single command buffer
	mov cx, 32
	rep stosb
	mov si, prompt			; Main loop; prompt for input
	call os_print_string
	mov ax, input			; Get command string from user
	call os_input_string

	call os_print_newline

	mov ax, input			; Remove trailing spaces
	call os_string_chomp

	mov si, input			; If just enter pressed, prompt again
	cmp byte [si], 0
	je draw_bck

	mov si, input			; Separate out the individual command
	mov al, ' '
	call os_string_tokenize

	mov word [param_list], di	; Store location of full parameters

	mov si, input			; Store copy of command for later modifications
	mov di, command
	call os_string_copy



	; First, let's check to see if it's an internal command...

	mov ax, input
	call os_string_uppercase
	mov si, input

	mov di, exit_string		; 'EXIT' entered?
	call os_string_compare
	jc near exit

	mov di, cls_string		; 'CLS' entered?
	call os_string_compare
	jc near clear_screen

	mov di, dir_string		; 'DIR' entered?
	call os_string_compare
	jc near list_directory

	mov di, ver_string		; 'VER' entered?
	call os_string_compare
	jc near print_ver

	mov di, time_string		; 'TIME' entered?
	call os_string_compare
	jc near print_time

	mov di, date_string		; 'DATE' entered?
	call os_string_compare
	jc near print_date

	mov di, cat_string		; 'CAT' entered?
	call os_string_compare
	jc near cat_file

	mov di, del_string		; 'DEL' entered?
	call os_string_compare
	jc near del_file

	mov di, copy_string		; 'COPY' entered?
	call os_string_compare
	jc near copy_file

	mov di, ren_string		; 'REN' entered?
	call os_string_compare
	jc near ren_file

	mov di, size_string		; 'SIZE' entered?
	call os_string_compare
	jc near size_file
 
    mov di,shut_string ; 'SHUT' entered?
	call os_string_compare
	jc near shutdown
	
	mov di, rboot_string ; 'REBOOT' entered?
	call os_string_compare
	jc near reboot
	
	mov di,hlt_string
	call os_string_compare
	jc near hlt_f
	
	mov di,mk_string
	call os_string_compare
	jc near new
	
	mov di,ext_string
	call os_string_compare
	jc near ext_read_start
	
	mov di,fda_string
	call os_string_compare
	jc near switch
	
	mov di,getip
	call os_string_compare
	jc ip
	
	; If the user hasn't entered any of the above commands, then we
	; need to check for an executable file -- .BIN or .BAS, and the
	; user may not have provided the extension

	
	
	mov ax, command
	call os_string_uppercase
	call os_string_length


	; If the user has entered, say, MEGACOOL.BIN, we want to find that .BIN
	; bit, so we get the length of the command, go four characters back to
	; the full stop, and start searching from there

	mov si, command
	add si, ax

	sub si, 4
	; Now we will check whether we are browsing Floppy Drive A: or Drive B:
	cmp dword [loc],'DISK'
	je LOAD
	cmp dword [loc],'EXTR'
	je extern_file
	jmp draw_bck
	.x_pos dw 0
	.y_pos dw 0
LOAD:
	mov di, bin_extension		; Is there a .BIN extension?
	call os_string_compare
	jc bin_file

	mov di, bas_extension		; Or is there a .BAS extension?
	call os_string_compare
	jc bas_file
	
	jmp no_extension

	
bin_file:
	mov ax, command
	mov bx, 0 ; Load 2 bytes
	mov cx, 0x8000
	call os_load_file
	jc total_fail
	; Now we will perform a file check..
	cmp word [0x8000],'NT' ; does the file name = NT?
	je execute_bin
	mov si,.err_format
	call os_print_string
	call os_print_newline
	jmp draw_bck
	.err_format db 'Error : Invalid Header!',0
execute_bin:
	mov ax,command
	mov bx,0
	mov cx,0x8000
	call os_load_file
	jc total_fail
	mov si, command
	mov di, kern_file_string
	mov cx, 6
	call os_string_strincmp
	jc no_kernel_allowed
	mov si, command
	mov di, ntload
	mov cx, 6
	call os_string_strincmp
	jc no_kernel_allowed
	mov ah,0x00
	mov al,0x03
	int 0x10
	mov ax,0x1003
	mov bx,0
	int 0x10
	mov ax, 0			; Clear all registers
	mov bx, 0
	mov cx, 0
	mov di, command
	mov word si, [param_list]
	call 32770			; Call the external program
	call os_print_newline
	MOV SI,basic_finished_msg
	call os_print_string
	call os_wait_for_key
	call os_print_newline
	call CMD_RESTART
	mov dh, 0
	mov dl, 0
	call os_move_cursor
	jmp clear_screen			; When program has finished, start again



bas_file:
	mov ax,param_list
	mov bx,0
	mov cx,0x8000
	call os_load_file
	jc total_fail
	jmp clear_screen
	

no_extension:
	mov ax, command
	call os_string_length

	mov si, command
	add si, ax

	mov byte [si], '.'
	mov byte [si+1], 'C'
	mov byte [si+2], 'O'
	mov byte [si+3], 'M'
	mov byte [si+4], 0

	mov ax, command
	mov bx, 0
	mov cx, 0x8000
	call os_load_file
	jc try_bas_ext
	cmp word [0x8000],'NT'
	je execute_bin


try_bas_ext:
	mov ax, command
	call os_string_length

	mov si, command
	add si, ax
	sub si, 4

	mov byte [si], '.'
	mov byte [si+1], 'B'
	mov byte [si+2], 'A'
	mov byte [si+3], 'S'
	mov byte [si+4], 0

	jmp bas_file



total_fail:
	mov si, invalid_msg
	call os_print_string

	jmp draw_bck


no_kernel_allowed:
	mov si, kern_warn_msg
	call os_print_string

	jmp draw_bck

extern_file:
	mov di,bas_extension
	call os_string_compare
	jc extern_bas_file
	mov ax, command
	mov bx, 0
	mov cx, 0x8000
	call ext_load_file
	jc total_fail_ext
	mov ax, 0			; Clear all registers
	mov bx, 0
	mov cx, 0
	mov dx, 0
	mov word si, [param_list]
	mov di, 0

	call 0x8000			; Call the external program
	call os_print_newline
	jmp draw_bck			; When program has finished, start again
extern_bas_file:
	jmp draw_bck
total_fail_ext:
	mov si, invalid_msg
	call os_print_string
	
	jmp draw_bck
; ------------------------------------------------------------------
new:
	mov word si, [param_list]
	call os_string_parse

	cmp ax, 0			; Were two filenames provided?
	jne .filename_provided

	mov si, nofilename_msg		; If not, show error message
	call os_print_string
	jmp draw_bck

.filename_provided:
	;mov cx, ax			; Store first filename temporarily
	;mov ax, bx			; Get destination
	call os_file_exists		; Check to see if it exists
	jnc .already_exists

	;mov ax, cx			; Get first filename back
	call os_create_file
	jc .failure

	mov si, .success_msg1
	call os_print_string
	jmp draw_bck

.already_exists:
	mov si, exists_msg
	call os_print_string
	jmp draw_bck

.failure:
	mov si, .failure_msg1
	call os_print_string
	jmp draw_bck


	.success_msg1	db 'File Created successfully', 13, 10, 0
	.failure_msg1	db 'Operation failed!', 13, 10, 0


; ------------------------------------------------------------------

clear_screen:
	pusha

	mov dx, 0			; Position cursor at top-left
	call os_move_cursor
	call os_clear_screen
	mov bl, [color]	; White on red
	mov dl, 0		; Start X position
	mov dh, 1		; Start Y position
	mov si, 115	; Width
	mov di, 50	; Finish Y position
	call os_draw_block
	call os_show_cursor
	jmp draw_bck


; ------------------------------------------------------------------

print_time:
	mov bx, tmp_string
	call os_get_time_string
	mov si, bx
	call os_print_string
	call os_print_newline
	jmp draw_bck


; ------------------------------------------------------------------

print_date:
	mov bx, tmp_string
	call os_get_date_string
	mov si, bx
	call os_print_string
	call os_print_newline
	jmp draw_bck


; ------------------------------------------------------------------

print_ver:
	mov si, version_msg
	call os_print_string
	jmp draw_bck


; ------------------------------------------------------------------

kern_warning:
	mov si, kern_warn_msg
	call os_print_string
	jmp draw_bck

reboot:
	 mov al,0xFE
	 out 0x64,al
; ------------------------------------------------------------------

list_directory:
	; We will check whether we are at floppy drive a: or b:
	; and show the files accordingly
	cmp dword [loc],'EXTR'
	je print_dir_2
	cmp dword [loc],'DISK'
	je print_dir_1
	JMP draw_bck
print_dir_2:
	;xor ax,ax
	;MOV CX,0
	mov ax,dirlist
	call read_ext_drive
	mov si,ax
	call os_print_string
	call os_print_newline
	jmp draw_bck	
print_dir_1:
		mov esi,someshit
	call os_print_string
	call os_print_newline
		call disk_read_root_dir         ; Load the root directory into disk_buffer
        jc .disk_error                  ; Carry is set on error - inform the user if there's a disk error
		mov si,info_disk
		call os_print_string
		call os_print_newline
        mov si, disk_buffer
		xor dx,dx
.repeat:
		
        push si
       
        mov al, [si+11]                 ; File attributes for entry
        cmp al, 0Fh                     ; Windows marker, skip it
        je .skip
 
        test al, 18h                    ; Is this a directory entry or volume label?
        jnz .skip                       ; Yes, ignore it
 
        mov al, [si]
        cmp al, 229                     ; If we read 229 = deleted filename
        je .skip
 
        cmp al, 0                       ; 1st byte = entry never used
        je .done
		
		
        mov al, 0                       ; Make sure tmp_string is zeroed out sufficently
        mov di, tmp_string
        mov cx, 14
        rep stosb
       
        mov di, tmp_string              ; Now we need to copy the filename over
        mov cx, 11
        rep movsb
       
        mov di, tmp_string              ; Locate the last character in the extension
        add di, 10
       
        mov al, [di]                    ; Move it right once.
        mov [di+1], al
        dec di                          ; Go back a step.
       
        mov al, [di]                    ; Do it again.
        mov [di+1], al
        dec di                          ; Back again.
       
        mov al, [di]                    ; Move it right once more.
        mov [di+1], al
        mov byte [di], ' '              ; And throw in a space to separate the filename and extension.
       
        mov si, tmp_string              ; And finally, display the formatted filename.
        call os_print_string
       
        mov si, .spaces                 ; Align everything up.
        call os_print_string
       
        pop si                          ; Get the beginning of the entry again
        push si                         ; And store it for safe-keeping.
       
        mov ax, [si+28]                 ; Get the file's size.
        call os_int_to_string           ; Convert it to a string and print it.
        mov si, ax
        call os_print_string
        call os_print_newline
		inc dx
	
.skip:
        pop si
        add si, 32                      ; Skip to the next directory entry
        jmp .repeat
 
.disk_error:
        mov si, .errmsg                 ; Uh oh, something went wrong with reading the disk!
        call os_print_string            ; Tell the user.
        jmp .done                       ; Bail out!
       
.done:
		call os_print_newline
		mov ax,dx
		call os_int_to_string
		mov si,ax
		call os_print_string
		mov si,files
		call os_print_string
		call os_print_newline
        pop si                          ; Unbreak the stack.
        call os_print_newline
		
		call os_print_string
        jmp draw_bck
       
        .errmsg         db 'Disk error',13,10,0
        .spaces         db '    ',0


; ------------------------------------------------------------------

cat_file:
	mov word si, [param_list]
	call os_string_parse
	cmp ax, 0			; Was a filename provided?
	jne .filename_provided

	mov si, nofilename_msg		; If not, show error message
	call os_print_string
	jmp draw_bck

.filename_provided:
	;call os_file_exists		; Check if file exists
	;jc .not_found
	cmp dword [loc],'DISK'
	je .INTERNAL_DISK
	cmp dword [loc],'EXTR'
	je .EXT_DISK
.INTERNAL_DISK:
	mov cx, 32768			; Load file into second 32K
	call os_load_file
	JC .not_found
	jmp .READ_IT
.EXT_DISK:
	mov cx,32768
	call ext_load_file
	jc .not_found
	jmp .READ_IT
.READ_IT:
	mov word [file_size], bx

	cmp bx, 0			; Nothing in the file?
	je draw_bck

	mov si, 32768
	mov ah, 0Eh			; int 10h teletype function
.loop:
	lodsb				; Get byte from loaded file

	cmp al, 0Ah			; Move to start of line if we get a newline char
	jne .not_newline

	call os_get_cursor_pos
	mov dl, 0
	call os_move_cursor

.not_newline:
	int 10h				; Display it
	dec bx				; Count down file size
	cmp bx, 0			; End of file?
	jne .loop

	jmp draw_bck

.not_found:
	mov si, notfound_msg
	call os_print_string
	jmp draw_bck


; ------------------------------------------------------------------
del_file:
	mov word si, [param_list]
	call os_string_parse
	cmp ax, 0			; Was a filename provided?
	jne .filename_provided

	mov si, nofilename_msg		; If not, show error message
	call os_print_string
	jmp draw_bck

.filename_provided:
	call os_remove_file
	jc .failure

	mov si, .success_msg
	call os_print_string
	mov si, ax
	call os_print_string
	call os_print_newline
	jmp draw_bck

.failure:
	mov si, .failure_msg
	call os_print_string
	jmp draw_bck


	.success_msg	db 'Deleted file: ', 0
	.failure_msg	db 'Could not delete file - does not exist or write protected', 13, 10, 0


; ------------------------------------------------------------------

size_file:
	mov word si, [param_list]
	call os_string_parse
	cmp ax, 0			; Was a filename provided?
	jne .filename_provided

	mov si, nofilename_msg		; If not, show error message
	call os_print_string
	jmp draw_bck

.filename_provided:
	call os_get_file_size
	jc .failure

	mov si, .size_msg
	call os_print_string

	mov ax, bx
	call os_int_to_string
	mov si, ax
	call os_print_string
	call os_print_newline
	jmp draw_bck


.failure:
	mov si, notfound_msg
	call os_print_string
	jmp draw_bck


	.size_msg	db 'Size (in bytes) is: ', 0


; ------------------------------------------------------------------

copy_file:
	mov word si, [param_list]
	call os_string_parse
	mov word [.tmp], bx

	cmp bx, 0			; Were two filenames provided?
	jne .filename_provided

	mov si, nofilename_msg		; If not, show error message
	call os_print_string
	jmp draw_bck

.filename_provided:
	mov dx, ax			; Store first filename temporarily
	mov ax, bx
	call os_file_exists
	jnc .already_exists
	cmp dword [loc],'DISK'
	je .INTERNAL_DISK
	cmp dword [loc],'EXTR'
	je .EXTERNAL_DISK
.INTERNAL_DISK:
	; The file is on the internal disk
	; We need to generate a duplicate
	mov ax, dx
	mov cx, 32768
	call os_load_file
	jc .load_fail

	mov cx, bx
	mov bx, 32768
	mov word ax, [.tmp]
	call os_write_file
	jc .write_fail

	mov si, .success_msg
	call os_print_string
	jmp draw_bck

.load_fail:
	mov si, notfound_msg
	call os_print_string
	jmp draw_bck

.write_fail:
	mov si, writefail_msg
	call os_print_string
	jmp draw_bck

.already_exists:
	mov si, exists_msg
	call os_print_string
	jmp draw_bck
.EXTERNAL_DISK:
	; We need to generate a copy of 
	; the file on the internal ROM
	mov ax, dx
	mov cx, 32768
	call ext_load_file
	jc .load_fail

	mov cx, bx
	mov bx, 32768
	mov word ax, [.tmp]
	call os_write_file
	jc .write_fail

	mov si, .success_msg
	call os_print_string
	jmp draw_bck

	.tmp		dw 0
	.success_msg	db 'File copied successfully', 13, 10, 0


; ------------------------------------------------------------------

ren_file:
	 mov word si, [param_list]
        call os_string_parse

	cmp bx, 0			; Were two filenames provided?
	jne .filename_provided

	mov si, nofilename_msg		; If not, show error message
	call os_print_string
	jmp draw_bck

.filename_provided:
	mov cx, ax			; Store first filename temporarily
	mov ax, bx			; Get destination
	call os_file_exists		; Check to see if it exists
	jnc .already_exists

	mov ax, cx			; Get first filename back
	call os_rename_file
	jc .failure

	mov si, .success_msg
	call os_print_string
	jmp draw_bck

.already_exists:
	mov si, exists_msg
	call os_print_string
	jmp draw_bck

.failure:
	mov si, .failure_msg
	call os_print_string
	jmp draw_bck


	.success_msg	db 'File renamed successfully', 13, 10, 0
	.failure_msg	db 'Operation failed - file not found or invalid filename', 13, 10, 0
shutdown:
	call os_clear_screen
	mov si,.ok
	call os_print_string
	cli
	hlt
	.ok db 'Safe to power off',0
; ------------------------------------------------------------------
; Switch Drives	
ext_read_start:
		mov dword [loc],0
		mov dword [prompt],'#pos'
		mov dword [prompt+4],'x86/'
		mov dword [prompt+8],'fd1:'
		MOV dword [loc],'EXTR'
		CALL ext_reset
		jmp draw_bck
switch:
	mov dword [prompt],'#pos'
	mov dword [prompt+4],'x86/'
	mov dword [prompt+8],'fd0:'
	mov dword [loc],'DISK'
	jmp draw_bck
exit:
	jmp draw_bck
; halt routine
hlt_f:
	mov si,.mac_str
	call os_print_string
	call INITIALIZE_PCI
	jmp draw_bck
	.mac_str db 'MAC Address : ',0
ip:
	mov si,.ip_str
	call os_print_string
	call os_get_ip
	jmp draw_bck
	.ip_str db 'IP Address : ',0
draw_bck:
	call os_get_cursor_pos
	mov [.pre_x],dl
	mov [.pre_y],dh
	mov dl, 0
	mov dh, 0
	call os_move_cursor
	mov ah, 09h			; Draw white bar at top
	mov bh, 0
	mov cx, 80
	mov bl, 0x1F
	mov al, ' '
	int 10h
	mov bx, tmp_string
	call os_get_time_string
	mov dl,72
	mov dh,0
	call os_move_cursor
	mov si,bx 
	call os_print_string
	mov dl,61
	mov dh,0
	call os_move_cursor
	mov bx, tmp_string
	call os_get_date_string
	mov si, bx
	call os_print_string
	mov dl,0
	mov dh,0
	call os_move_cursor
	mov si,lol
	call os_print_string
	mov dl,20
	mov dh,0
	call os_move_cursor
	mov dl,[.pre_x]
	mov dh,[.pre_y]
	call os_move_cursor
	;call os_print_newline
	call os_show_cursor
	jmp get_cmd
	.pre_x dw 0
	.pre_y dw 0
CMD_RESTART:
	xor bl,bl
	mov ax,0x1112
	int 0x10
	mov ax,0x1003
	mov bx,0
	int 0x10
	mov bl, [color]	; White on red
	mov dl, 0		; Start X position
	mov dh, 1		; Start Y position
	mov si, 115	; Width
	mov di, 50	; Finish Y position
	call os_draw_block
	jmp draw_bck
; ------------------------------------------------------------------
; Some Data
	lol db 'POSNT 1.1.7.2 Type PCGUI for GUI',0
	count dw 0
	someshit db 'Directory of DEV/FD0/:',0
	files db ' file(s)',0
	color dw 0x0F
; ==================================================================

